package cn.wolfcode.common.web.interceptor;

import cn.wolfcode.common.constants.CommonConstants;
import cn.wolfcode.common.domain.UserInfo;
import cn.wolfcode.common.web.CommonCodeMsg;
import cn.wolfcode.common.web.Result;
import cn.wolfcode.common.web.anno.RequireLogin;
import cn.wolfcode.redis.CommonRedisKey;
import com.alibaba.fastjson.JSON;
import org.apache.commons.lang.StringUtils;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


public class RequireLoginInterceptor implements HandlerInterceptor {
    private StringRedisTemplate redisTemplate;

    public RequireLoginInterceptor(StringRedisTemplate redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    /**
     * 前置拦截
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //HandlerMethod : 请求映射方法信息(方法所在类，方法信息， 映射路劲， 方法上注解， 方法参数......)封装对象,看你的请求是否在访问Controller
        if (handler instanceof HandlerMethod) {
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            //从请求头中获取FEIGN_REQUEST,看它是浏览器访问过来的，还是feign访问过来的
            String feignRequest = request.getHeader(CommonConstants.FEIGN_REQUEST_KEY);
            //1：判断当前请求对应请求映射方法是否贴@RequireLogin标签,且是经过网关的用户请求，就是从浏览器过来的请求
            if (!StringUtils.isEmpty(feignRequest) && CommonConstants.FEIGN_REQUEST_FALSE.equals(feignRequest) && handlerMethod.getMethodAnnotation(RequireLogin.class) != null) {
                //设置响应类型
                response.setContentType("application/json;charset=utf-8");
                //获取请求头token信息 userToken:token  userInfo
                String token = request.getHeader(CommonConstants.TOKEN_NAME);
                //判断token是否为空
                if (StringUtils.isEmpty(token)) {
                    //返回 登录超时,请重新登录
                    response.getWriter().write(JSON.toJSONString(Result.error(CommonCodeMsg.TOKEN_INVALID)));
                    return false;
                }
                //使用token，从redis中把值取出来，然后转换为userInfo对象
                UserInfo userInfo = JSON.parseObject(redisTemplate.opsForValue().get(CommonRedisKey.USER_TOKEN.getRealKey(token)), UserInfo.class);
                //如果userInfo为空
                if (userInfo == null) {
                    //1.token不是redis中生成的，可能是伪造的
                    //2.redis中的token失效了 过期了
                    //{code:-2,msg:"登录超时"}
                    response.getWriter().write(JSON.toJSONString(Result.error(CommonCodeMsg.TOKEN_INVALID)));
                    return false;
                }
                //登录安全校验
                //获取请求头中真实ip信息
                String ip = request.getHeader(CommonConstants.REAL_IP);
                //与真实ip对比
                if (!userInfo.getLoginIp().equals(ip)) {
                    //ip不一致,token可能被别人窃取. {code:-3,msg:"登录IP发生改变,请重新登录"}
                    response.getWriter().write(JSON.toJSONString(Result.error(CommonCodeMsg.LOGIN_IP_CHANGE)));
                    return false;
                }
            }
        }
        return true;
    }
}

